<?php

/**
 * Default Formatter
 */
 
class Formatter {
	/**
	 * Registers formats and formatters
	 */
	protected $registry;
	
	/**
	 * Default constructor
	 */
	public function __construct() {
		$this->registry = array();
		$this->setFormatter('datetime', array($this, 'formatDatetime'));
		$this->setFormatter('date', array($this, 'formatDate'));
		$this->setFormatter('year', array($this, 'formatYear'));				
		$this->setFormatter('month', array($this, 'formatMonth'));
		$this->setFormatter('day', array($this, 'formatDay'));
		$this->setFormatter('time', array($this, 'formatTime'));		
		$this->setFormatter('hour', array($this, 'formatHour'));
		$this->setFormatter('minutes', array($this, 'formatMinutes'));		
		$this->setFormatter('percentage', array($this, 'formatPercentage'));
		$this->setFormatter('memory', array($this, 'formatMemory'));
		$this->setFormatter('ip', array($this, 'formatIP'));
		$this->setFormatter('country', array($this, 'formatCountry'));		
		$this->setFormatter('number', array($this, 'formatNumber'));
		$this->setFormatter('nowrap', array($this, 'formatNowrap'));
	}
	
	/**
	 * Registers the formatter for the specified format. In case that another formatter
	 is already registered for that format, the old formatter will be removed and the new
	 will be registered.
	 * 
	 * @param string format the format name
	 * @param mixed formatter a callable function
	 */
	public function setFormatter($format, $formatter) {
		if ( !empty($format) ) {	
			$this->registry[$format] = $formatter;
		}
	}
	
	/**
	 * Formats the value with the specified format
	 * 
	 * @param mixed value the value to be formatted
	 * @param string format the format to be applied
	 */
	public function format($value, $format) {
		if ( isset($this->registry[$format]) ) {
			if ( is_callable($this->registry[$format]) ) {
				$value = call_user_func($this->registry[$format], $value);
			}
			return $value;
		}
	}
	
	//
	// D E F A U L T   F O R M A T T E R S
	//
	
	//
	// Numbers / Metrics
	//
	protected function formatNumber($value) {
		$prec = ( floatval($value) == intval($value) ) ? 0 : 2;
		return number_format($value, $prec, '.', ' ');
	}
	protected function formatMemory($value) {
		$value = floatval($value);
		
		$units = array('bytes', 'KB', 'MB', 'GB', 'TB');
		
		for ( $i=0; $i<count($units); $i++ ) {
			if ( $value < 100 ) {
				return ( $this->format($value, 'number') .' '. $units[$i] );
			}		
			$value = $value / 1024;
		}
		
		$value = $value * 1024;
		return ( $this->format($value, 'number') .' '. $units[($i-1)] );
	}
	
	protected function formatPercentage($value) {
		if ( !is_percentage($value) ) {
			return $value;
		}

		preg_match('/^([0-9]+(.[0-9]+))?%$/', $value, $matches);
		$value = $matches[1];		
		return ( $this->format($value, 'number') .'%' );
	}
	
	//
	// Text
	//
	protected function formatNowrap($value) {
		return ( '<div class="nowrap">'. $value .'</div>' );
	}
	
	protected function formatIP($value) {
		return '<a href="http://www.ripe.net/perl/whois?submit=Submit+Query&query='. $value .'" title="RIPE report for '. $value .'">'. $value .'</a>';
	}	
	
	protected function formatCountry($value) {
		static $countryCodes = array('AD'=>'Andorra','AE'=>'United Arab Emirates','AF'=>'Afghanistan','AG'=>'Antigua and Barbuda','AI'=>'Anguilla','AL'=>'Albania','AM'=>'Armenia','AN'=>'Netherlands Antilles','AO'=>'Angola','AQ'=>'Antarctica','AR'=>'Argentina','AS'=>'American Samoa','AT'=>'Austria','AU'=>'Australia','AW'=>'Aruba','AX'=>'Åland Islands','AZ'=>'Azerbaijan','BA'=>'Bosnia and Herzegovina','BB'=>'Barbados','BD'=>'Bangladesh','BE'=>'Belgium','BF'=>'Burkina Faso','BG'=>'Bulgaria','BH'=>'Bahrain','BI'=>'Burundi','BJ'=>'Benin','BM'=>'Bermuda','BN'=>'Brunei Darussalam','BO'=>'Bolivia','BR'=>'Brazil','BS'=>'Bahamas','BT'=>'Bhutan','BV'=>'Bouvet Island','BW'=>'Botswana','BY'=>'Belarus','BZ'=>'Belize','CA'=>'Canada','CC'=>'Cocos (Keeling) Islands','CD'=>'Congo, the Democratic Republic of the','CF'=>'Central African Republic','CG'=>'Congo','CH'=>'Switzerland','CI'=>'Côte d\'Ivoire','CK'=>'Cook Islands','CL'=>'Chile','CM'=>'Cameroon','CN'=>'China','CO'=>'Colombia','CR'=>'Costa Rica','CU'=>'Cuba','CV'=>'Cape Verde','CX'=>'Christmas Island','CY'=>'Cyprus','CZ'=>'Czech Republic','DE'=>'Germany','DJ'=>'Djibouti','DK'=>'Denmark','DM'=>'Dominica','DO'=>'Dominican Republic','DZ'=>'Algeria','EC'=>'Ecuador','EE'=>'Estonia','EG'=>'Egypt','EH'=>'Western Sahara','ER'=>'Eritrea','ES'=>'Spain','ET'=>'Ethiopia','FI'=>'Finland','FJ'=>'Fiji','FK'=>'Falkland Islands (Malvinas)','FM'=>'Micronesia, Federated States of','FO'=>'Faroe Islands','FR'=>'France','GA'=>'Gabon','GB'=>'United Kingdom','GD'=>'Grenada','GE'=>'Georgia','GF'=>'French Guiana','GG'=>'Guernsey','GH'=>'Ghana','GI'=>'Gibraltar','GL'=>'Greenland','GM'=>'Gambia','GN'=>'Guinea','GP'=>'Guadeloupe','GQ'=>'Equatorial Guinea','GR'=>'Greece','GS'=>'South Georgia and the South Sandwich Islands','GT'=>'Guatemala','GU'=>'Guam','GW'=>'Guinea-Bissau','GY'=>'Guyana','HK'=>'Hong Kong','HM'=>'Heard Island and McDonald Islands','HN'=>'Honduras','HR'=>'Croatia','HT'=>'Haiti','HU'=>'Hungary','ID'=>'Indonesia','IE'=>'Ireland','IL'=>'Israel','IM'=>'Isle of Man','IN'=>'India','IO'=>'British Indian Ocean Territory','IQ'=>'Iraq','IR'=>'Iran, Islamic Republic of','IS'=>'Iceland','IT'=>'Italy','JE'=>'Jersey','JM'=>'Jamaica','JO'=>'Jordan','JP'=>'Japan','KE'=>'Kenya','KG'=>'Kyrgyzstan','KH'=>'Cambodia','KI'=>'Kiribati','KM'=>'Comoros','KN'=>'Saint Kitts and Nevis','KP'=>'Korea, Democratic People\'s Republic of','KR'=>'Korea, Republic of','KW'=>'Kuwait','KY'=>'Cayman Islands','KZ'=>'Kazakhstan','LA'=>'Lao People\'s Democratic Republic','LB'=>'Lebanon','LC'=>'Saint Lucia','LI'=>'Liechtenstein','LK'=>'Sri Lanka','LR'=>'Liberia','LS'=>'Lesotho','LT'=>'Lithuania','LU'=>'Luxembourg','LV'=>'Latvia','LY'=>'Libyan Arab Jamahiriya','MA'=>'Morocco','MC'=>'Monaco','MD'=>'Moldova, Republic of','ME'=>'Montenegro','MG'=>'Madagascar','MH'=>'Marshall Islands','MK'=>'Macedonia, the former Yugoslav Republic of','ML'=>'Mali','MM'=>'Myanmar','MN'=>'Mongolia','MO'=>'Macao','MP'=>'Northern Mariana Islands','MQ'=>'Martinique','MR'=>'Mauritania','MS'=>'Montserrat','MT'=>'Malta','MU'=>'Mauritius','MV'=>'Maldives','MW'=>'Malawi','MX'=>'Mexico','MY'=>'Malaysia','MZ'=>'Mozambique','NA'=>'Namibia','NC'=>'New Caledonia','NE'=>'Niger','NF'=>'Norfolk Island','NG'=>'Nigeria','NI'=>'Nicaragua','NL'=>'Netherlands','NO'=>'Norway','NP'=>'Nepal','NR'=>'Nauru','NU'=>'Niue','NZ'=>'New Zealand','OM'=>'Oman','PA'=>'Panama','PE'=>'Peru','PF'=>'French Polynesia','PG'=>'Papua New Guinea','PH'=>'Philippines','PK'=>'Pakistan','PL'=>'Poland','PM'=>'Saint Pierre and Miquelon','PN'=>'Pitcairn','PR'=>'Puerto Rico','PS'=>'Palestinian Territory, Occupied','PT'=>'Portugal','PW'=>'Palau','PY'=>'Paraguay','QA'=>'Qatar','RE'=>'RÃƒÂ©union','RO'=>'Romania','RS'=>'Serbia','RU'=>'Russian Federation','RW'=>'Rwanda','SA'=>'Saudi Arabia','SB'=>'Solomon Islands','SC'=>'Seychelles','SD'=>'Sudan','SE'=>'Sweden','SG'=>'Singapore','SH'=>'Saint Helena','SI'=>'Slovenia','SJ'=>'Svalbard and Jan Mayen','SK'=>'Slovakia','SL'=>'Sierra Leone','SM'=>'San Marino','SN'=>'Senegal','SO'=>'Somalia','SR'=>'Suriname','ST'=>'Sao Tome and Principe','SV'=>'El Salvador','SY'=>'Syrian Arab Republic','SZ'=>'Swaziland','TC'=>'Turks and Caicos Islands','TD'=>'Chad','TF'=>'French Southern Territories','TG'=>'Togo','TH'=>'Thailand','TJ'=>'Tajikistan','TK'=>'Tokelau','TL'=>'Timor-Leste','TM'=>'Turkmenistan','TN'=>'Tunisia','TO'=>'Tonga','TR'=>'Turkey','TT'=>'Trinidad and Tobago','TV'=>'Tuvalu','TW'=>'Taiwan, Province of China','TZ'=>'Tanzania, United Republic of','UA'=>'Ukraine','UG'=>'Uganda','UM'=>'United States Minor Outlying Islands','US'=>'United States','UY'=>'Uruguay','UZ'=>'Uzbekistan','VA'=>'Holy See (Vatican City State)','VC'=>'Saint Vincent and the Grenadines','VE'=>'Venezuela','VG'=>'Virgin Islands, British','VI'=>'Virgin Islands, U.S.','VN'=>'Viet Nam','VU'=>'Vanuatu','WF'=>'Wallis and Futuna','WS'=>'Samoa','YE'=>'Yemen','YT'=>'Mayotte','ZA'=>'South Africa','ZM'=>'Zambia','ZW'=>'Zimbabwe');	// ISO 3166-1 alpha-2 codes
		
		$value = strtoupper($value);
		$value = ( $value == 'UK' ) ? 'GB' : $value;
		if ( isset($countryCodes[$value]) ) {
			$label = '<abbr title="'. $countryCodes[$value] .'">'. $value .'</abbr>';
			$label = '<img src="'. Cinnamon::registry('view')->getUrl('images/flags/') . strtolower($value) .'.gif" alt="'. $value .' Flag" />&nbsp;'. $label;
		} else {
			$label = 'Unknown';
		}
		
		return $label;
	}
	
	//
	// Date and Time
	//
	protected function formatDatetime($value) {
		$config = Cinnamon::registry('config');
		$dateFormat = $config->get('date.format');

		$value = gmstrtotime($value);
		
		// apply formatting
		if ( $dateFormat == 'custom' ) {
			return gmdate($config->get('date.custom'), $value);
		} else if ( $dateFormat == 'classic' ) {
			return gmdate('F jS, Y H:i a', $value);
		} else if ( $dateFormat == 'relative' ) {
			// dont ignore selected site offset
			$db = Cinnamon::registry('db');
			$site_id = Cinnamon::registry('session')->get('filters.site');
			$offset = $db->getValue('SELECT utc_offset FROM '. $db->sites .' WHERE site_id='. intval($site_id));
			return time_since($value, $offset);
		}
	}
	
	protected function formatDate($value) {
		$value = gmstrtotime($value);
		return gmdate('F jS, Y', $value);	
	}
	
	protected function formatMonth($value) {
		$value = gmstrtotime($value);
		return gmdate('F Y', $value);
	}

	
	protected function formatDay($value) {
		$value = gmstrtotime($value);
		
		$now = gmdate('Y-m');
		$then = gmdate('Y-m', $value);
		
		if ( strcmp($now, $then) == 0 ) {
			$diff = intval( gmdate('d') ) - intval( gmdate('d', $value) );
			if ( $diff == 0 ) {
				return 'Today';
			} else if ( $diff == 1 ) {
				return 'Yesterday';
			}
		}
	
		return gmdate('l', $value);
	}
	
	protected function formatTime($value) {
		$value = gmstrtotime($value);
		return gmdate('g:i:s a', $value);	
	}
	
	protected function formatMinutes($value) {
		$value = gmstrtotime($value);
		return gmdate('g:i a', $value);
	}
	
	protected function formatHour($value) {
		$value = gmstrtotime($value);
		return gmdate('g a', $value);		
	}	
}

?>
